package com.ncepu.clubmanagement.utils.fileSaveUtilsImpl;

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.CopyObjectRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.ncepu.clubmanagement.utils.FileSaveUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;

@Component
public class AliOSSUtils implements FileSaveUtils {

    @Autowired
    private AliOSSProperties aliOSSProperties;

    // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
    private String endpoint;

    private String region;

    private EnvironmentVariableCredentialsProvider credentialsProvider;

    private ClientBuilderConfiguration clientBuilderConfiguration;

    // 填写Bucket名称，例如examplebucket。
    private String bucketName;

    private OSS ossClient;

    public AliOSSUtils() throws com.aliyuncs.exceptions.ClientException {

        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 创建OSSClient实例。
        clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
    }



    @Override
    @Transactional
    public String upload(MultipartFile file, String path) {

        endpoint = aliOSSProperties.getEndpoint();
        region = aliOSSProperties.getRegion();
        bucketName = aliOSSProperties.getBucketName();


        // 建立ossClient连接
        ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();


        // 获取文件名称。
        String origionalObjectName = file.getOriginalFilename();
        // 避免文件名称覆盖(UUID技术)
        String objectName = UUID.randomUUID().toString() + origionalObjectName;
        // 确定包含路径下文件上传的位置
        objectName  = path + "/" + objectName;

        try {
            InputStream inputStream = file.getInputStream();   // 使用前端传入的文件，因此是文件流的形式
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 创建PutObject请求。
            ossClient.putObject(putObjectRequest);

            return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException();
        }

        finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        // 返回空，代表上传失败
        return null;
    }

    @Override
    @Transactional
    public String upload(MultipartFile file, String path, String fileName) {

        endpoint = aliOSSProperties.getEndpoint();
        region = aliOSSProperties.getRegion();
        bucketName = aliOSSProperties.getBucketName();

        // 建立ossClient连接
        ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        // 确定包含路径下文件上传的位置
        String objectName = path + "/" + fileName;

        try {
            InputStream inputStream = file.getInputStream();   // 使用前端传入的文件，因此是文件流的形式
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 创建PutObject请求。
            ossClient.putObject(putObjectRequest);

            return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();  // 确保Transactional的回滚机制能够正常工作
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        // 返回空，代表上传失败
        return null;
    }

    @Override
    @Transactional
    public boolean delete(String path) {

        endpoint = aliOSSProperties.getEndpoint();
        region = aliOSSProperties.getRegion();
        bucketName = aliOSSProperties.getBucketName();


        // 建立ossClient连接
        ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            path = extractKey(path);
            ossClient.deleteObject(bucketName, path);
            return true;
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
            // ... 其他错误处理
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }



        // 删除失败
        return false;
    }

    public String generateFileUrl(String path, String fileName) {
        endpoint = aliOSSProperties.getEndpoint();
        bucketName = aliOSSProperties.getBucketName();

        // 确定包含路径下文件上传的位置
        String objectName = path + "/" + fileName;

        // 生成文件的URL
        String fileUrl = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;

        return fileUrl;
    }

    @Override
    @Transactional
    public String upload(MultipartFile file, String path, String fileName, String customUrl) {

        endpoint = aliOSSProperties.getEndpoint();
        region = aliOSSProperties.getRegion();
        bucketName = aliOSSProperties.getBucketName();

        // 建立ossClient连接
        ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        // 确定包含路径下文件上传的位置
        String objectName = path + "/" + customUrl.substring(customUrl.lastIndexOf('/') + 1);

        try {
            InputStream inputStream = file.getInputStream();   // 使用前端传入的文件，因此是文件流的形式
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 创建PutObject请求。
            ossClient.putObject(putObjectRequest);

            // 如果用户指定了自定义URL，则使用该URL；否则，使用默认方式生成URL
            String fileUrl = (customUrl != null && !customUrl.isEmpty()) ? customUrl : endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
            return fileUrl;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();  // 确保Transactional的回滚机制能够正常工作
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        // 返回空，代表上传失败
        return null;
    }

    @Override
    @Transactional
    public boolean replaceFile(String sourceUrl, String destinationUrl) {

        endpoint = aliOSSProperties.getEndpoint();
        region = aliOSSProperties.getRegion();
        bucketName = aliOSSProperties.getBucketName();

        String sourceKey = extractKey(sourceUrl);
        String destinationKey = extractKey(destinationUrl);

        // 建立ossClient连接
        ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();


        try {
            // 复制对象
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, sourceKey, bucketName, destinationKey);
            ossClient.copyObject(copyObjectRequest);

            // 删除原对象
            sourceUrl = extractKey(sourceUrl);
            ossClient.deleteObject(bucketName, sourceUrl);

            System.out.println("文件替换成功！");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("文件替换过程中发生错误。");
            return false;
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }

        return true;
    }

    private static String extractKey(String url) {
        // 示例URL格式: https://web-tlias-2024-12-4.oss-cn-beijing.aliyuncs.com/affair/53c13638-0180-4ca7-b675-2831ae44d17412affair
        try {
            // 使用URL解析来提取路径
            URL ossUrl = new URL(url);
            String path = ossUrl.getPath();
            return path.substring(1); // 移除路径开头的'/'
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null; // 或者抛出异常，根据您的错误处理策略来决定
        }
    }

}
